perm filename GEMSUB[GEO,BGB] blob sn#081312 filedate 1974-01-15 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00011 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00003 00002	TITLE GEMSUB GEOMETRIC MODELING SYSTEM SUBROUTINES.
C00004 00003	TITLE ARITH  -  ARITHMETIC ROUTINES.
C00007 00004	SUBR(SIN)
C00009 00005	SUBR(ATAN,X)		ARC TANGENT
C00012 00006	SUBR(ATAN2,DY,DX)	ARC TANGENT (DELTA-Y,DELTA-X)
C00015 00007	TITLE III    - III DISPLAY SUBROUTINES - BGB - JANUARY 1973.
C00016 00008	SUBRS DPYSET,DPYBIG,DPYBRT	Set buffer,char. size, brightness*
C00018 00009	SUBRS AVECT,AIVECT,RVECT,RIVECT	Vectors
C00021 00010	SUBRS DPYSTR,DTYO,DPYOUT	Output string,character, POG	*
C00023 00011	SUBRS OCTDPY,DECDPY,FLODPY	Numeric display			*
C00026 ENDMK
C⊗;
TITLE GEMSUB; GEOMETRIC MODELING SYSTEM SUBROUTINES.

	INTERNAL FATAL.,WARN.
	EXTERNAL PDL
	EXTERNAL JOBCNI,JOBAPR,JOBTPC,JOBREL,JOBHRL,JOBDDT
	EXTERNAL JOBREN,JOBOPC,JOBSA

	P←17


;FATAL ERROR MESSAGE.

FATAL.:	OUTSTR[BYTE(7)15,12,106,101,124↔"AL - "⊗1↔0]
	LAC 0,@(P)↔OUTSTR @0↔INCHRW↔GO .-1↔LIT
WARN.:	OUTSTR[BYTE(7)15,12,(21)"WAR"↔"NING "⊗1↔0]
	LAC 0,@(P)↔OUTSTR @0↔INCHRW↔GO .-1↔LIT
;TITLE ARITH  -  ARITHMETIC ROUTINES.

	HALFPI↑:	201622077325 ;PI/2
	PI↑:		202622077325 ;PI
	TWOPI↑:		203622077325 ;2*PI

SUBR(SQRT,X)		;SQUARE ROOT OF ABS(X).
COMMENT ⊗------------------------------------------------------------
⊗
	A←←0 ↔ B←←1 ↔ C←←2
	LACM B,X↔JUMPE B,POP1J.↔PUSHP 2

;LET X=F*(2↑2B) WHERE 0.25<F<1.00 THEN SQRT(X)=SQRT(F)*(2↑B).
	ASHC B,-=27↔SUBI B,201	;GET EXPONENT IN B, FRACTION IN C.
	ROT B,-1		;CUT EXP IN HALF, SAVE ODD BIT
	DAP B,L↔LSH B,-=35	;USE THAT ODD BIT.
	ASH C,-10↔FSC C,177(B)	;0.25 < FRACTION < 1.00

;LINEAR APPROXIMATION TO SQRT(F).
	DAC C,A
	FMP C,[0.8125↔0.578125](B)
	FAD C,[0.302734↔0.421875](B)

;TWO ITERATIONS OF NEWTON'S METHOD.
	LAC B,A
	FDV B,C↔FAD C,B↔FSC C,-1
	FDV A,C↔FADR A,C
     L: FSC A,0↔LAC 1,A↔POPP 2
	POP1J
ENDR SQRT; BGB 28 DECEMBER 1972 -------------------------------------

SUBR(LOG,X)	;NATURAL LOGRITHM.
COMMENT ⊗------------------------------------------------------------
⊗
	MOVM X↔SKIPE 1,0↔CAMN 0,[1.0]↔POP1J
	ASHC 0,-33↔ADDI 0,211000↔MOVSM 0,TMP1#
	MOVSI 0,(-128.5)↔FADM 0,TMP1
	ASH 1,-10↔TLC 1,200000↔FAD 1,[-0.70710678]
	LAC 0,1↔FAD 0,[1.4142135]↔FDV 1,0
	DAC 1,TMP2#↔FMP 1,1
	LAC 0,[0.59897864]↔FMP 0,1
	FAD 0,[0.96147063]↔FMP 0,1
	FAD 0,[2.88539120]↔FMP 0,TMP2↔FAD 0,TMP1
	FMP 0,[0.69314718]↔LAC 1,0↔POP1J
	VAR
ENDR LOG;---------------------------------------------------------
SUBR(SIN)
	GO SIN.↔ENDR SIN
SUBR(COS)
	GO COS.↔ENDR COS
	
BEGIN SINCOS			;MODIFIED OLDE LIB40 SINE & COSINE - BGB.
	A←←1 ↔ B←←2 ↔ C←←3
↑COS.:	SKIPA A,ARG1
↑SIN.:	SKIPA A,ARG1
	FADR  A,HALFPI			;COS(X) = SIN(X+π/2).
	MOVM B,A↔CAMG B,[17B5]↔POP1J	;FOR SMALL X, SIN(X)=X.

;B ← (ABS(X)MODULO 2π)/HALFPI
;C ← QUADRANT 0, 1, 2 OR 3.
	FDVR B,HALFPI
	LAC C,B↔FIX C,233000
	CAILE C,3↔GO[
	TRZ C,3↔FSC C,233
	FSBR B,C↔GO .-3]		;MODULO 2π.
	GO .+1(C)↔GO .+4↔JFCL↔GO[
	FSBRI B,(2.0)↔MOVNS B↔GO .+2]	;SIN(X+π)=SIN(-X)
	FSBRI B,(4.0)			;SIN(X+2π)=SIN(X)
	SKIPGE A↔MOVNS	B		;SIN(-X) = -SIN(X).

;FOR -1 ≤ B ≤ +1 REPRESENTING -π/2 ≤ X ≤ +π/2,
;COMPUTE SINE(X) APPROXIMATION BY TAYLOR SERIES.
	DAC B,C↔FMPR B,B	
	LAC A,[164475536722]↔FMP A,B
	FAD A,[606315546346]↔FMP A,B
	FAD A,[175506321276]↔FMP A,B
	FAD A,[577265210372]↔FMP A,B
	FAD A,HALFPI↔FMPR A,C↔POP1J
	LIT
BEND SINCOS;---------------------------------------------------------
SUBR(ATAN,X)		;ARC TANGENT
COMMENT ⊗------------------------------------------------------------
	IF 0.0 < X ≤ 1.0 THEN ⊂ Z ← X*X;
	RETURN (ATAN(X) = X*(B0+A1/(Z+B1-A2/(Z+B2-A3/(Z+B3)))));⊃;
	IF X>1 THEN ATAN(X) = PI/2 - ATAN(1/X);
	IF X>1 THEN RH(D) =-1, AND LH(D) = -SGN(X)
	IF X<1, THEN RH(D) = 0, AND LH(D) =  SGN(X)
⊗
	A←←1 ↔ B←←2 ↔ C←←3 ↔ D←←4 ↔ E←←5
	LAC	A,X		;PICK UP THE ARGUMENT IN A
ATAN1:	LACM	B, A		;GET ABSF OF ARGUMENT
	CAMG	B, A1		;IF X<2↑-33, THEN RETURN WITH...
	POP1J		;ATAN(X) = X
	HLLO	D, A		;SAVE SIGN, SET RH(D) = -1
	CAML	B, A2		;IF A>2↑33, THEN RETURN WITH
	GO[LAC A,HALFPI ↔POP1J];	ATAN(X) = PI/2
	MOVSI	C,(<1.0>)	;FORM 1.0 IN C
	CAMG	B, C		;IS ABSF(X)>1.0?
	TRZA	D, -1		;IF B ≤ 1.0, THEN RH(D) = 0
	FDVM	C, B		;B IS REPLACED BY 1.0/B
	TLC	D, (D)		;XOR SIGN WITH > 1.0 INDICATOR

	DAC B,E↔FMP B,B
	LAC C,B↔FAD C,KB3↔LAC A,KA3↔FDVM A,C
	FAD C,B↔FAD C,KB2↔LAC A,KA2↔FDVM A,C
	FAD C,B↔FAD C,KB1↔LAC A,KA1↔FDV  A,C
	FAD A,KB0↔FMP A,E

	TRNE	D, -1		;CHECK > 1.0 INDICATOR
	FSB	A, HALFPI		;ATAN(A) = -(ATAN(1/A)-PI/2)
	SKIPGE	D		;LH(D) = -SGN(B) IF B>1.0
	MOVNS A		;NEGATE ANSWER
	POP1J		;EXIT
A1:	145000000000		;2↑-33
A2:	233000000000		;2↑33

KB0:	176545543401		;0.1746554388
KB1:	203660615617		;6.762139240
KB2:	202650373270		;3.316335425
KB3:	201562663021		;1.448631538

KA1:	202732621643		;3.709256262
KA2:	574071125540		;-7.106760045
KA3:	600360700773		;-0.2647686202
ENDR ATAN;--------------------------------------------------------
SUBR(ATAN2,DY,DX)	;ARC TANGENT (DELTA-Y,DELTA-X)
COMMENT ⊗------------------------------------------------------------
⊗
; OMEGA ← ATAN2(Y,X).
	Y←←1 ↔ X←←2
	LACM Y,ARG2↔LACM X,ARG1
	CAMN X,Y↔JUMPE Y,L2
	CAML Y,X↔GO L1

;HORIZONTAL TO π/2; ABS(Y) < ABS(X).
	LAC  Y,ARG2↔FDVR Y,ARG1
	PUSH 17,Y↔PUSHJ 17,ATAN		;ARCTAN(Y/X)
	SKIPL ARG1↔POP2J		;1ST & 2ND QUADRANTS.
	JUMPGE Y,[
	FSBR Y,PI↔POP2J]		;3RD QUADRANT.
	FADR Y,PI↔POP2J			;2ND QUADRANT.

;VERTICAL TO π/2; ABS(X) < ABS(Y).
L1:	LACN X,ARG1↔FDVR X,ARG2
	PUSH 17,X↔PUSHJ 17,ATAN		;ARCTAN(X/Y)
	SKIPG ARG2↔GO[
	FSB Y,HALFPI↔POP2J]
	FADR Y,HALFPI
L2:	POP2J

ENDR ATAN2;----------------------------------------------------------

SUBR(ASIN,X)	;ARC SINE.
COMMENT ⊗------------------------------------------------------------
	ASIN(X)=ATAN(X/SQRT(1-X↑2)).
	GIVEN -1 ≤ X ≤ +1 RETURN -π/2 ≤ ASIN(X) ≤ +π/2.
⊗
	A←1 ↔ B←2
	LACN A,X↔FMPR A,X↔FADRI A,(1.0)
	JUMPE A,[LAC A,HALFPI		;WAS X EITHER -1.0 OR 1.0?
	SKIPGE ARG1↔MOVNS A↔POP1J]
	CALL(SQRT,A)
	LAC B,X↔FDVR B,1↔DAC B,X	;CALCULATE X/SQRT(1-X↑2)
	GO ATAN			;CALCULATE ATAN(SQRT(1-X↑2))
ENDR ASIN;-----------------------------------------------------------

SUBR(ACOS,X)	;ARC COSINE.
COMMENT ⊗------------------------------------------------------------
	ACOS(X)= π/2 - ASIN(X).
	GIVEN -1 ≤ X ≤ +1 RETURN 0 ≤ ACOS(X) ≤ +π.
⊗
	CALL(ASIN,X)
	MOVNS 1↔FADR 1,HALFPI
	POP1J
ENDR ACOS;--------------------------------------------------------
;TITLE III    - III DISPLAY SUBROUTINES - BGB - JANUARY 1973.

	↓A←1↔↓B←2↔↓C←3
INTERN BUFDPY,DPYPTR
BUFDPY:	.+2↔=100↔BLOCK =100

INTERN DPYBUF
DPYBUF:	DPYBU.↔=4048 
DPYBU.: BLOCK =4048

IGNORE:	BLOCK 1
SIZBRT:	BLOCK 1
DPYCOL:	BLOCK 1
DPYPTR:	BLOCK 1
BUFEND:	BLOCK 1
BUFHD:	BLOCK 2		;UPG ARGUMENT. ;ADDRESS ↔ LENGTH.
DDSAVE:	BLOCK 1

;VERNIER III TEXT POSITIONING.
	VERNX ←← 14
	VERNY ←← 11

;DISPLAY SAIL STRING.
DPYSST↑: POP 16,1↔POP 16,2↔SKIPGE IGNORE↔POPJ P,
	HRRZS 2			;LENGTH	OF STRING.
	JUMPLE 2,SSRET
	ILDB 3,1
	IDPB 3,DPYPTR
	SOJG 2,.-2
SSRET:	HRRZ 1,DPYPTR
	CAML 1,BUFEND
	SETOM IGNORE
	POPJ P,
;SUBRS DPYSET,DPYBIG,DPYBRT	;Set buffer,char. size, brightness*

SUBR(DPYSET,BUFFER)	;Initialize a display buffer			*
;____________________________________________________________________
	LAC 1,BUFFER↔CDR 2,-1(1)	;BUFFER SIZE.
	ADDI 2,-1(1)↔DAC 2,BUFEND
	ADDI 1,2↔DAC 1,BUFHD		;POINT TO THIRD WORD.
	SETZM IGNORE
	SETZM SIZBRT
CLR2:	LAC A,BUFHD	;BLIT THE BUFFER WITH THE III-TEXT OPCODE 1.
	LACI B,1↔DAC B,1(A)
	LACI B,2(A)↔LIPI B,1(A)
	BLT B,@BUFEND
	PUSH P,(P)↔GO LV3
ENDR DPYSET

SUBR(DPYBIG,SIZE)	;Set character size
;____________________________________________________________________
;USES AC 1
	LAC A,SIZE↔DPB A,[POINT 3,SIZBRT,27]	;REMEMBER NEW SIZE
	POP1J
ENDR DPYBIG
;____________________________________________________________________

SUBR(DPYBRT,SIZE)	;Set brightness
;USES AC 1
	LAC A,SIZE↔DPB A,[POINT 3,SIZBRT,24]	;REMEMBER NEW BRIGHTNESS
	POP1J
ENDR DPYBRT
;SUBRS AVECT,AIVECT,RVECT,RIVECT	;Vectors
COMMENT ⊗
	The  III display  processor  is  a stored  program  computer,
these  III subroutines  make  a III  program using  only  two display
operations: the  long vector operation  and the  text operation.  The
pointer to the display buffer is  always maintained as a BYTE POINTER
to  the last character displayed.  The flag named  IGNORE is set when
display buffer  overflow occurs  and  all further  display calls  are
ignored  until the buffer  is used.  The III instruction  formats are
given below, unlike  most CPU  (but like must  display processors  of
its day)  the immediate data  fields are in  the left portion  of the
instruction and the opcode in the right.
	TEXT DISPLAY WORD:	 ASCII/ABCDE/ + 1
	LONG VECTOR  WORD:  BYTE(11)X,Y(3)BRT,SIZ(7)OPCODE
The  long vector opcodes appear in the following four lines: ⊗

	SUBR(RIVECT)
		GO RIV.	↔ENDR RIVECT
	SUBR(RVECT)
		GO RV.	↔ENDR RVECT
	SUBR(AIVECT)
		GO AIV.	↔ENDR AIVECT
	SUBR(AVECT)
		GO AV.	↔ENDR AVECT

;USES AC 1-3
;DTYO DEPENDS ON THIS
RIV.:	SKIPA C,[046]		;RELATIVE INVISIBLE VECTOR.
RV.:	LACI  C, 006 ↔GO LV0	;RELATIVE   VISIBLE VECTOR.
AIV.:	SKIPA C,[146]		;ABSOLUTE INVISIBLE VECTOR.
AV.:	LACI  C, 106		;ABSOLUTE   VISIBLE VECTOR.
	SETZM DPYCOL		;RESET TAB LOCATION

LV0:	SKIPGE IGNORE↔POP2J
LV:	LAC A,-2(P)↔LAC B,-1(P)		;PICKUP X AND Y.
LVC:	DPB A,[POINT 11,C,10]		;PACK X INTO III-WORD.
	DPB B,[POINT 11,C,21]		;PACK Y INTO III-WORD.
	SKIPE A,SIZBRT			;NEW BRIGHTNESS OR SIZE?
	GO [ IOR C,A↔DZM SIZBRT↔GO LV2]	;YES, SET IT
LV2:	AOS A,DPYPTR↔DAC C,(A)		;PACK WORD INTO III-BUFFER.
LV3:	LIPI A,<(<POINT 7,0,35>)>	;UPDATE DPYPTR...
	DAC A,DPYPTR↔LACI A,(A)		;WHICH IS A BYTE-POINTER.
	CAML A,BUFEND↔SETOM IGNORE	;CHECK FOR BUFFER OVERFLOW.
	POP2J
;SUBRS DPYSTR,DTYO,DPYOUT	;Output string,character, POG	*
;--------------------------------------------------------------------

SUBR(DPYSTR,TEXT)
;USES AC 1,3
	LAC 3,TEXT↔LIPI 3,440700
L1:	ILDB 3↔JUMPE POP1J.
	CALL(DTYO,0)↔GO L1
ENDR DPYSTR;---------------------------------------------------------

SUBR(DTYO,CHAR)
;USES AC 1
;DPYSTR DEPENDS ON DTYO NOT CLOBBERING 3
	SKIPE SIZBRT
	GO [ PUSHP 0↔PUSHP 2↔PUSHP 3
	     CALL(RIVECT,[0],[0])
	     POPP 3↔POPP 2↔POPP 0
	     GO .+1]
	LAC 1,CHAR
	CAIN 1,15↔DOM DPYCOL
	CAIN 1,11↔GO DOTAB
DTYO1:	IDPB 1,DPYPTR↔AOS DPYCOL
	CDR 1,DPYPTR↔CAML 1,BUFEND
	DOM IGNORE↔POP1J
DOTAB:	CALL(DTYO,[" "])	;We got a tab, put out spaces until
	LAC 1,DPYCOL		;column is divisible by 8
	TRNE 1,7↔GO DOTAB
	CDR 1,DPYPTR
	POP1J
ENDR DTYO;-----------------------------------------------------------

SUBR(DPYOUT,POG)
COMMENT ⊗------------------------------------------------------------
⊗↔	SKIPN A,BUFHD↔GO L1
	LAC 2,DPYPTR↔DAC 2,-2(1)
	LACI 2,2(2)↔SUB 2,1↔DAC 2,-1(1)

L1:	CDR B,DPYPTR↔SUB B,BUFHD		;BUFFER LENGTH.
	AOS B↔DAC B,BUFHD+1

	LACM A,POG↔DPB A,[POINT 4,UPGOP,12]	;GLASS TO AC FIELD.
	XCT UPGOP
	POP1J
UPGOP:	703B8+BUFHD
ENDR DPYOUT;---------------------------------------------------------
;SUBRS OCTDPY,DECDPY,FLODPY	;Numeric display			*
;--------------------------------------------------------------------

SUBR(OCTDPY,INTEGER)	;OCTAL NUMBER DISPLAY.
	Q←15 ↔ N←13
	JFCL↔GO L2
	LAC 14,INTEGER↔LAC Q,[POINT 3,14,-1]↔LACI N,6
L1:	ILDB Q↔IORI 60↔CALL(DTYO,0)↔SOJG N,L1
	CALL(DTYO,[" "])
L2:	LAC 14,INTEGER↔LAC Q,[POINT 3,14,17]↔LACI N,6
L3:	ILDB Q↔IORI 60↔CALL(DTYO,0)↔SOJG N,L3
	POP1J
ENDR OCTDPY;3/25/73(BGB)---------------------------------------------

DECDPY↑:;(INTEGER)	;DECIMAL NUMBER DISPLAY.
BEGIN DECDPY
	LAC 1,ARG1↔POP P,-1(P)		;FETCH ARG AND LAC RET. ADR.
L1:	JUMPGE 1,L2			;TEST FOR NEGATIVE NUMBER.
	MOVM 2,1↔CALL(DTYO,["-"])	;PRINT MINUS SIGN.
	LAC 1,2
L2:	IDIVI 1,12↔PUSH P,2		;MODULO TEN AND SAVE.
	SKIPE 1↔PUSHJ P,L2		;TEST FOR DONE.
	POP P,1↔ADDI 1,60↔CALL(DTYO,1)	;RESTORE & PRINT.
	POPJ P,
BEND DECDPY;12/17/72(BGB)--------------------------------------------

SUBR(FLODPY,FLONUM,PLACES)	;FLOATING NUMBER DISPLAY.
	LAC FLONUM
	JUMPL[CALL(DTYO,["-"])↔LACM FLONUM↔GO .+1]
	LACM 2,PLACES↔CAILE 2,6↔LACI 2,6↔DAC 2,PLACES
	FMPR[1.↔10.↔100.↔1000.↔10000.↔100000.↔1000000.](2)↔FIXX
	IDIV[=1↔=10↔=100↔=1000↔=10000↔=100000↔=1000000](2)
	PUSHP 1↔CALL(DECDPY,0)↔POPP 0
	LAC 2,PLACES
	ADD[=1↔=10↔=100↔=1000↔=10000↔=100000↔=1000000](2)
	PUSHP DPYPTR↔CALL(DECDPY,0)↔POPP 1
	LACI "."↔IDPB 0,1
	POP2J
ENDR FLODPY;12/17/72(BGB)--------------------------------------------
END